/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nys.conci.usuario.servicio;

import com.nys.conci.backend.entidad.InformacionUsuario;
import com.nys.conci.base.ServicioBase;
import com.nys.conci.base.excepcion.ExcepcionServicio;
import com.nys.conci.cliente.entidad.Cliente;
import com.nys.conci.cliente.entidad.Persona;
import com.nys.conci.usuario.entidad.Usuario;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.Query;
import org.primefaces.component.terminal.Terminal;

/**
 * Clase Servicio que se contiene la lógica del negocio relacionada con las
 * personas. Contiene los métodos que acceden a la capa de persistencia, y
 * funciones con lógica del negocio.
 *
 * @author Yeudy10
 * @since 03/02/2013
 */
@Stateless
@TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public class ServicioControlUsuario extends ServicioBase {

    /**
     * Método que consulta una lista de personas por medio del tipo, ya sea
     * usuarios o clientes
     *
     * @param tipo Tipo de persona que se va a consultar
     * @return lista de personas o null
     */
    public List<Persona> consultarPersonas(String tipo) {
        try {
            List<Persona> lista = new ArrayList<Persona>();
            String consulta = "SELECT s FROM Persona s where tipo = :tipo or tipo = 'A'";
            lista = em.createQuery(consulta, Persona.class).setParameter("tipo", tipo).getResultList();
            return lista;
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Personas",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarPersonas()",
                    ex, getClass());
        }
    }
    
    
    /**
     * Método que consulta una lista de personas por medio del tipo, ya sea
     * usuarios o clientes
     *
     * @param tipo Tipo de persona que se va a consultar
     * @return lista de personas o null
     */
    public List<Persona> consultarPersonasCitas(String tipo) {
        try {
            List<Persona> lista = new ArrayList<Persona>();
            String consulta = "SELECT DISTINCT (p.*) FROM persona p, control_cita cc where (tipo = :tipo or tipo = 'A') and cc.fechareal = CURRENT_DATE and cc.identificacion_c = p.identificacion";
            lista = em.createNativeQuery(consulta, Persona.class).setParameter("tipo", tipo).getResultList();
            return lista;
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Personas",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarPersonas()",
                    ex, getClass());
        }
    }    

    /**
     * Método que consulta una lista de personas por medio del tipo, ya sea
     * usuarios o clientes y el email
     *
     * @param tipo Tipo de persona que se va a consultar
     * @return lista de personas o null
     */
    public boolean consultarExisteUsuarioCorreo(String tipo, String correo) {
        try {
            List<Persona> lista = new ArrayList<Persona>();
            String consulta = "SELECT s FROM Persona s where tipo = :tipo or tipo = 'A' and email = :correo";
            lista = em.createQuery(consulta, Persona.class).setParameter("tipo", tipo).setParameter("correo", correo).getResultList();
            if (lista != null && !lista.isEmpty()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Personas",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarPersonas()",
                    ex, getClass());
        }
    }

    /**
     * Método que consulta una lista de personas por medio de la identificacion
     * y el email de la persona
     *
     * @param identificaicon identificacion de la persona
     * @param correo correo de la persona
     * @return lista de personas o null
     */
    public boolean consultarExisteCorreo(String identificacion, String correo) {
        try {
            List<Persona> lista = new ArrayList<Persona>();
            String consulta = "SELECT s.* FROM persona s where identificacion <> :identificacion and  email = :correo";
            lista = em.createNativeQuery(consulta, Persona.class).setParameter("identificacion", identificacion).setParameter("correo", correo).getResultList();
            if (lista != null && !lista.isEmpty()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Personas",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarExisteCorreo(String identificacion, String correo)",
                    ex, getClass());
        }
    }

    /**
     * Método que consulta una lista de personas por medio del tipo, ya sea
     * usuarios o clientes
     *
     * @param tipo Tipo de persona que se va a consultar
     * @return lista de personas o null
     */
    public Persona consultarUsuarioCorreo(String tipo, String correo) {
        try {
            List<Persona> lista = new ArrayList<Persona>();
            String consulta = "SELECT s FROM Persona s where (tipo = :tipo or tipo = 'A') and email = :correo";
            lista = em.createQuery(consulta, Persona.class).setParameter("tipo", tipo).setParameter("correo", correo).getResultList();
            if (lista != null && !lista.isEmpty()) {
                lista.get(0);
            } else {
                return null;
            }
            return lista.get(0);
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Personas",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarPersonas()",
                    ex, getClass());
        }
    }

    /**
     * Método que consulta una lista de personas por medio del tipo, ya sea
     * usuarios o clientes
     *
     * @param tipo Tipo de persona que se va a consultar
     * @return lista de personas o null
     */
    public List<Persona> consultarPersonas(String tipo, Integer estado) {
        try {
            List<Persona> lista = new ArrayList<Persona>();
            String cons = "";
            if (tipo != null && !tipo.trim().equals("")) {
                cons = " and u.tipo_usuario = :tipo";
            }

            if (estado != null && estado != 0) {
                cons = cons + " and u.id_estado =  :estado";
            }

            String consulta = "select p.* from persona p,usuario u where u.identificacion = p.identificacion " + cons;
            Query q = em.createNativeQuery(consulta, Persona.class);

            if (tipo != null && !tipo.trim().equals("")) {
                q.setParameter("tipo", tipo);
            }

            if (estado != null && estado != 0) {
                q.setParameter("estado", estado);
            }

            lista = q.getResultList();
            return lista;
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Personas",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarPersonas(String tipo, Integer estado, String especialidad)",
                    ex, getClass());
        }
    }

    /**
     * Método que consulta una lista de personas por medio del tipo, ya sea
     * usuarios o clientes
     *
     * @param tipo Tipo de persona que se va a consultar
     * @return lista de personas o null
     */
    public List<Persona> consultarPersonasClientes(Integer id_estado, Integer id_plan_pago) {
        try {
            List<Persona> lista = new ArrayList<Persona>();
            String cons = "";
            if (id_estado != null && id_estado != 0) {
                cons = " and c.id_estado = :id_estado";
            }

            if (id_plan_pago != null && id_plan_pago != 0) {
                cons = cons + " and p.identificacion in (select pc.identificacion_c from plan_cliente pc, cliente c where "
                        + "pc.identificacion_c = c.identificacion and "
                        + "pc.id_plan_pago = :id_plan_pago) ";
            }

            String consulta = "select p.* from persona p,cliente c where p.identificacion =  c.identificacion  " + cons;
            Query q = em.createNativeQuery(consulta, Persona.class);

            if (id_estado != null && id_estado != 0) {
                q.setParameter("id_estado", id_estado);
            }

            if (id_plan_pago != null && id_plan_pago != 0) {
                q.setParameter("id_plan_pago", id_plan_pago);
            }

            lista = q.getResultList();
            return lista;
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Clientes",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarPersonas(String tipo, Integer estado, String especialidad)",
                    ex, getClass());
        }
    }

    /**
     * Método que consulta una persona por medio de la identificación
     *
     * @param identificacion Identificacion que se va a consultar
     * @return Objeto de tipo Persona
     */
    public Persona consultarPersona(String identificacion) {
        try {
            List<Persona> persona = new ArrayList<Persona>();
            String consulta = "SELECT s FROM Persona s where identificacion = :identificacion";
            persona = em.createQuery(consulta, Persona.class).setParameter("identificacion", identificacion).getResultList();
            if (persona != null && !persona.isEmpty()) {
                return persona.get(0);
            } else {
                return null;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo el listado de Personas",
                    "Ha ocurrido un error obteniendo el listado de Personas. En " + getClass() + ".consultarPersonas()",
                    ex, getClass());
        }
    }

    /**
     * Método que consulta un usuario por medio de la identificación
     *
     * @param identificacion Identificación que se va a consultar
     * @return Objeto de tipo usuario o null si no existiera
     */
    public Usuario consultarUsuario(String identificacion) {
        try {
            List<Usuario> usuario = new ArrayList<Usuario>();
            String consulta = "SELECT s FROM Usuario s where identificacion = :identificacion";
            usuario = em.createQuery(consulta, Usuario.class).setParameter("identificacion", identificacion).getResultList();
            if (usuario != null && !usuario.isEmpty()) {
                return usuario.get(0);
            } else {
                return null;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo un usuario",
                    "Ha ocurrido un error obteniendo unusuario. En " + getClass() + ".consultarUsuario(String identificacion)",
                    ex, getClass());
        }
    }
    
    
    /**
     * Método que consulta un usuario por medio del id del estado
     *
     * @param id_estado id del estado
     * @return Objeto de tipo usuario o null si no existiera
     */
    public Usuario consultarUsuarioIdEstado(Integer id_estado) {
        try {
            List<Usuario> usuario = new ArrayList<Usuario>();
            String consulta = "SELECT s FROM Usuario s where id_estado = :id_estado";
            usuario = em.createQuery(consulta, Usuario.class).setParameter("id_estado", id_estado).getResultList();
            if (usuario != null && !usuario.isEmpty()) {
                return usuario.get(0);
            } else {
                return null;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo un usuario",
                    "Ha ocurrido un error obteniendo unusuario. En " + getClass() + 
                    ".consultarUsuarioIdEstado(Integer id_estado)",
                    ex, getClass());
        }
    }    

    /**
     * Método que consulta un usuario por medio de la identificación y el
     * password
     *
     * @param identificacion Identificación que se va a consultar
     * @param pass_word password que se va a consultar
     * @return Objeto de tipo usuario o null si no existiera
     */
    public Usuario consultarUsuarioLogin(String identificacion, String pass_word) {
        try {
            List<Usuario> usuario = new ArrayList<Usuario>();
            String consulta = "SELECT s FROM Usuario s where identificacion = :identificacion and pass_word = :pass_word";
            usuario = em.createQuery(consulta, Usuario.class).setParameter("identificacion", identificacion).setParameter("pass_word", pass_word).getResultList();
            if (usuario != null && !usuario.isEmpty()) {
                return usuario.get(0);
            } else {
                return null;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo un usuario",
                    "Ha ocurrido un error obteniendo unusuario. En " + getClass() + ".consultarUsuarioLogin(String identificacion, String pass_word)",
                    ex, getClass());
        }
    }
    
    
/**
     * Obtiene la informacion de una usuario
     *
     * @param codigo_usuario Codigo de usuario a consultar
     * @return InformacionUsuario con la datos solicitados
     */
    public InformacionUsuario obtenerInformacionUsuario(String codigo_usuario, String password) {
        InformacionUsuario info = new InformacionUsuario();
        Usuario usu = new Usuario();
                usu = consultarUsuarioLogin(codigo_usuario, password);        
        if(usu == null){
            throw new ExcepcionServicio("Usuario o contraseña no existe",
                "Usuario Inválido",
                getClass());
        }
        
        Persona persona = consultarPersona(usu.getIdentificacion());
        if(persona == null){
            throw new ExcepcionServicio("Usuario inválido",
                "Usuario inválido",
                getClass());
        }        
        
        
        try {
            info.setId_usuario(usu.getIdentificacion());
            info.setTipo_usuario(usu.getTipo_usuario());
            info.setNombre(persona.getNombre()+" "+persona.getApellido1()+" "+persona.getApellido2());
                        

        } catch (Exception ex) {
            throw new ExcepcionServicio("Error al obtener la información del usuario",
                    "Error al obtener información del usuario, método obtenerInformacionUsuario, clase ServicioControlUsuario.java",
                    ex, ServicioControlUsuario.class);
        }

        return info;
    }    

    /**
     * Método que consulta un cliente por medio de la identificación
     *
     * @param identificacion Identificación que se va a consultar
     * @return Objeto de tipo cliente o null si no existiera
     */
    public Cliente consultarCliente(String identificacion) {
        try {
            List<Cliente> usuario = new ArrayList<Cliente>();
            String consulta = "SELECT s FROM Cliente s where identificacion = :identificacion";
            usuario = em.createQuery(consulta, Cliente.class).setParameter("identificacion", identificacion).getResultList();
            if (usuario != null && !usuario.isEmpty()) {
                return usuario.get(0);
            } else {
                return null;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo un Cliente",
                    "Ha ocurrido un error obteniendo un cliente. En " + getClass() + ".consultarCliente(String identificacion)",
                    ex, getClass());
        }
    }
    
    /**
     * Método que consulta un cliente por medio del estado
     *
     * @param identificacion id_estado que se va a consultar
     * @return Objeto de tipo cliente o null si no existiera
     */
    public Cliente consultarClienteIdEstado(Integer id_estado) {
        try {
            List<Cliente> usuario = new ArrayList<Cliente>();
            String consulta = "SELECT s FROM Cliente s where id_estado = :id_estado";
            usuario = em.createQuery(consulta, Cliente.class).setParameter("id_estado", id_estado).getResultList();
            if (usuario != null && !usuario.isEmpty()) {
                return usuario.get(0);
            } else {
                return null;
            }
        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error obteniendo un Cliente",
                    "Ha ocurrido un error obteniendo un cliente. En " + getClass() + 
                    ".consultarClienteIdEstado(Integer id_estado)",
                    ex, getClass());
        }
    }    

    /**
     * Método que guarda o actualiza una persona
     *
     * @param persona persona que se va a guardar
     * @param modificar variable que indica si se va a actualizar o guardar
     */
    public void guardarPersona(Persona persona, boolean modificar) {
        try {
            if (modificar) {
                actualizar(persona);
            } else {
                guardar(persona);
            }

        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error al guardar la persona",
                    "Ha ocurrido un error al guardar la persona. En " + getClass() + ".guardarPersona()",
                    ex, getClass());
        }
    }

    /**
     * Método que guarda o actualiza un cliente
     *
     * @param cliente cliente que se va a guardar
     * @param modificar variable que indica si se va a actualizar o guardar
     */
    public void guardarCliente(Cliente cliente, boolean modificar) {
        try {
            if (modificar) {
                actualizar(cliente);
            } else {
                guardar(cliente);
            }

        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error al guardar un cliente",
                    "Ha ocurrido un error al guardar un cliente. En " + getClass() + ".guardarCliente(Cliente cliente, boolean modificar)",
                    ex, getClass());
        }
    }

    /**
     * Método que guarda o actualiza un Usuario
     *
     * @param persona usuario que se va a guardar
     * @param modificar variable que indica si se va a actualizar o guardar
     */
    public void guardarUsuario(Usuario usuario, boolean modificar) {
        try {
            if (modificar) {
                actualizar(usuario);
            } else {
                guardar(usuario);
            }

        } catch (Exception ex) {
            throw new ExcepcionServicio("Ha ocurrido un error al guardar el usuario",
                    "Ha ocurrido un error al guardar el usuario. En " + getClass() + ".guardarUsuario()",
                    ex, getClass());
        }
    }
}
